package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.SmsPullPojo;
import com.xbongbong.paas.pojo.SmsSpacePojo;
import com.xbongbong.paas.pojo.dto.PaasFormDataEsMappingDTO;
import com.xbongbong.paas.pojo.dto.SmsCronTabAsyncDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.SMSSpaceService;
import com.xbongbong.paas.service.SmsSendService;
import com.xbongbong.paas.service.dynamic.crm.strategy.DynamicStrategyFactory;
import com.xbongbong.paas.service.dynamic.crm.strategy.SmsDynamicStrategy;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.CommentUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.MapConstant;
import com.xbongbong.pro.dynamic.pojo.dto.DynamicSmsDTO;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ClueErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.service.toolbox.sms.SMSMarketService;
import com.xbongbong.pro.service.toolbox.sms.SMSNoticeService;
import com.xbongbong.pro.sms.model.SmsConfigModel;
import com.xbongbong.pro.sms.model.SmsStatusModel;
import com.xbongbong.pro.sms.pojo.SmsExplainPojo;
import com.xbongbong.pro.sms.pojo.SmsImportExcelResultPojo;
import com.xbongbong.pro.sms.pojo.SmsListAndCountPojo;
import com.xbongbong.pro.sms.pojo.SmsLogPojo;
import com.xbongbong.pro.sms.pojo.SmsReceiverPojo;
import com.xbongbong.pro.sms.pojo.SmsSendTemplatePojo;
import com.xbongbong.pro.sms.pojo.dto.SmsAvailableCountDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsCancelSendDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsImportExcelResultDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsLogListDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsLogStatisticDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsRabbitMqDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsSendTemplateListDTO;
import com.xbongbong.pro.sms.pojo.dto.SmsUpdateStatusDTO;
import com.xbongbong.pro.sms.pojo.vo.SmsCancelSendVO;
import com.xbongbong.pro.sms.pojo.vo.SmsGetAvailableCountVO;
import com.xbongbong.pro.sms.pojo.vo.SmsImportExcelResultVO;
import com.xbongbong.pro.sms.pojo.vo.SmsLogListVO;
import com.xbongbong.pro.sms.pojo.vo.SmsLogStatisticVO;
import com.xbongbong.pro.sms.pojo.vo.SmsSendTemplateListVO;
import com.xbongbong.pro.sms.pojo.vo.SmsUpdateStatusVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.SmsSetConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ClueUserEntity;
import com.xbongbong.saas.domain.entity.CustomerUserEntity;
import com.xbongbong.saas.domain.entity.SmsConfigEntity;
import com.xbongbong.saas.domain.entity.SmsStatusEntity;
import com.xbongbong.saas.domain.entity.SmsTemplateEntity;
import com.xbongbong.saas.domain.entity.ext.ClueEntityExt;
import com.xbongbong.saas.domain.entity.ext.ContactEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.SmsModuleTypeEnum;
import com.xbongbong.saas.enums.SmsSendTypeEnum;
import com.xbongbong.saas.enums.SmsStatusEnum;
import com.xbongbong.saas.enums.SmsTemplateSendApiEnum;
import com.xbongbong.saas.enums.SmsTemplateStatusEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.ClueUserModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.SmsTemplateModel;
import com.xbongbong.saas.service.ContactService;
import com.xbongbong.saas.service.CustomerService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.help.SysEnvHelp;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.common.Strings;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.domain.PageRequest;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.xbongbong.paas.toolbox.util.DateUtil.SDFYMDHM;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @description: 短信发送
 * @Author: hongxiao
 * @date: 2019-01-18 15:59
 */
@Service("smsSendService")
public class SmsSendServiceImpl implements SmsSendService {

    private static final Logger LOG = LoggerFactory.getLogger(SmsSetServiceImpl.class);

    @Resource
    private SmsConfigModel smsConfigModel;
    @Resource
    private SmsTemplateModel smsTemplateModel;
    @Resource
    private UserModel userModel;
    @Resource
    private SmsStatusModel smsStatusModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private CustomerService customerService;
    @Resource
    private ContactService contactService;
    @Resource
    private ClueModel clueModel;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private ClueUserModel clueUserModel;


    @Resource
    private DynamicStrategyFactory dynamicStrategyFactory;
    @Resource
    private SysEnvHelp sysEnvHelp;

    @Override
    public SmsGetAvailableCountVO getAvailableCount(SmsAvailableCountDTO smsAvailableCountDTO) throws XbbException {
        SmsGetAvailableCountVO smsGetAvailableCountVO = new SmsGetAvailableCountVO();
        try {
            String corpid = smsAvailableCountDTO.getCorpid();

            // 可用短信条数
            Integer smsCounts = 0;
            SmsConfigEntity smsSign = smsConfigModel.getEntityByCorpid(corpid);
            if (smsSign != null) {
                smsCounts = smsSign.getSmsCount() == null ? Integer.valueOf(0) : smsSign.getSmsCount();
            }
            smsGetAvailableCountVO.setSmsCounts(smsCounts);

        } catch (Exception e) {
            LOG.error("发送短信初始化短信", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return smsGetAvailableCountVO;
    }

    @Override
    public SmsSendTemplateListVO templateList(SmsSendTemplateListDTO smsSendTemplateListDTO) throws XbbException {
        SmsSendTemplateListVO smsSendTemplateListVO = new SmsSendTemplateListVO();
        String corpid = smsSendTemplateListDTO.getCorpid();
        String nameLike = smsSendTemplateListDTO.getNameLike();
        // 客户或联系人等业务列表不传nameLike,不用添加退订回T
        boolean nullNameFlag = nameLike == null;

        nameLike = nameLike != null ? nameLike.trim() : null;

        String sign = "";

        // 短信模板
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("status", SmsTemplateStatusEnum.APPROVAL_SUCCESS.getCode());
        param.put("nameLike", nameLike);
        param.put("corpid", corpid);

        List<SmsTemplateEntity> templateList;

        SmsConfigEntity smsSign;
        try {
            smsSign = smsConfigModel.getEntityByCorpid(corpid);
            if (smsSign != null) {
                sign = "【" + smsSign.getSign() + "】";
            }
            templateList = smsTemplateModel.findEntitys(param);
        } catch (Exception e) {
            LOG.error("获取发送短信可用的短信模板错误", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        List<SmsSendTemplatePojo> templatePojoList = new ArrayList<>();
        if (templateList != null && templateList.size() > 0) {
            for (SmsTemplateEntity entity : templateList) {
                StringBuffer content = new StringBuffer();
                content.append(sign + entity.getContent());
                // 客户联系人列表发送短信时，非营销帐号不添加退订回T
                if(nullNameFlag) {
                    if(entity.getSendApi().equals(SmsTemplateSendApiEnum.NEW_MARKET_AMOUNT.getCode())
                            || entity.getSendApi().equals(SmsTemplateSendApiEnum.SPACE_IMAGINATION_MARKET_AMOUNT.getCode())) {
                        if(!entity.getContent().contains(I18nMessageUtil.getMessage(SmsSetConstant.SMS_BACK_T))){
                            content.append(I18nMessageUtil.getMessage(SmsSetConstant.SMS_BACK_T));
                        }
                    }
                } else {
                    if(!entity.getContent().contains(I18nMessageUtil.getMessage(SmsSetConstant.SMS_BACK_T))){
                        content.append(I18nMessageUtil.getMessage(SmsSetConstant.SMS_BACK_T));
                    }
                }

                // 可发送短信条数
                Integer count = 1;
                if (content.length() > SmsSetConstant.SMS_MAX_LENGTH) {
                    count = content.length() / SmsSetConstant.SMS_REAL_LENTTH;
                    count += (content.length() % SmsSetConstant.SMS_REAL_LENTTH == 0) ? 0 : 1;
                }

                SmsSendTemplatePojo templatePojo = new SmsSendTemplatePojo();
                templatePojo.setTemplateId(entity.getId());
                templatePojo.setName(entity.getName());
                Integer businessType = smsSendTemplateListDTO.getBusinessType();
                String contentString = content.toString();
                // 如果是客户，将线索负责人去掉，如果是线索将客户负责人去掉，如果是联系人，这两者都去掉
                if (Objects.equals(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), businessType)) {
                    contentString = contentString.replaceAll("\\{" + I18nMessageUtil.getMessage(CommonConstant.CLUE_MAIN_USER) + "\\}", " ");
                } else if (Objects.equals(XbbRefTypeEnum.CLUE.getCode(), businessType)) {
                    String regex = "\\{" + I18nMessageUtil.getMessage(CommonConstant.CUSTOMER_MAIN_USER) + "\\}";
                    contentString = contentString.replaceAll(regex, " ");
                } else if (Objects.equals(XbbRefTypeEnum.CONTACT.getCode(), businessType)) {
                    String regexCustomer = "\\{" + I18nMessageUtil.getMessage(CommonConstant.CUSTOMER_MAIN_USER) + "\\}";
                    String regexClue = "\\{" + I18nMessageUtil.getMessage(CommonConstant.CLUE_MAIN_USER) + "\\}";
                    contentString = contentString.replaceAll(regexCustomer, " ");
                    contentString = contentString.replaceAll(regexClue, " ");
                }
                templatePojo.setContent(contentString);

                templatePojo.setSendCounts(count);
                templatePojo.setSendApi(entity.getSendApi());
                templatePojoList.add(templatePojo);
            }
        }
        smsSendTemplateListVO.setList(templatePojoList);

        // 是否有编辑权限
        boolean smsSetUpdate = Objects.nonNull(smsSendTemplateListDTO.getLoginUser())
                && (smsSendTemplateListDTO.getLoginUser().isAdminOrBoss() || smsSendTemplateListDTO.getLoginUser().getPermSet().contains(ProPermissionAliasEnum.SMS_SET_UPDATE.getAlias()));
        smsSendTemplateListVO.setIsEdit(smsSetUpdate);

        if(smsSign == null){
            smsSendTemplateListVO.setSmsSign(null);
        } else {
            String smsConfigSign = smsSign.getSign() == null ? null : sign;
            smsSendTemplateListVO.setSmsSign(smsConfigSign);
        }
        smsSendTemplateListVO.setSmsSign(sign);
        return smsSendTemplateListVO;

    }

    /**
     * 发送短信
     *
     * @param smsRabbitMqDTO 入参
     * @return
     * @throws XbbException
     * @author youli.chen
     * @date: 2019-01-25 19:45
     * @version 1.0
     * @since v1.0
     */
    @Override
    public void send(SmsRabbitMqDTO smsRabbitMqDTO) throws XbbException {
        String corpid = smsRabbitMqDTO.getCorpid();
        String userId = smsRabbitMqDTO.getUserId();

        String sender = "";
        if (Objects.equals(PaasConstant.SYS_USER_ID, userId)) {
            sender = I18nMessageUtil.getMessage(PaasConstant.SYS_GENERATED);
        } else {
            UserEntity userEntity = userModel.getByKey(userId, corpid);
            if (userEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004, SystemErrorCodeEnum.API_ERROR_100004.getMsg());
            }
            sender = userEntity.getName();
        }

        // 短信发送类型
        Integer sendType = smsRabbitMqDTO.getSendType();
        if (sendType == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信发送类型不能为空");
        }
        LOG.info("send ---> sendType" + sendType);

        List<Integer> sendTypeList = Arrays.asList(SmsSendTypeEnum.AT_ONCE.getCode(), SmsSendTypeEnum.DELAY.getCode());
        if (!sendTypeList.contains(sendType)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, "短信发送类型只能选即时发送或定时发送");
        }
        // 短信发送时间
        String dates = smsRabbitMqDTO.getDates();
        long sendTime = checkSendTime(sendType, dates);
        LOG.info("send ---> sendTime" + sendTime);

        // 发送短信接口获取需要发送短信的列表以及条数
        SmsListAndCountPojo smsListAndCountPojo = new SmsListAndCountPojo();
        sendSmsListAndCount(smsListAndCountPojo, smsRabbitMqDTO, corpid, userId, sender, sendType);
        List<SmsStatusEntity> statusLists = smsListAndCountPojo.getStatusLists();
        Integer sendCounts = smsListAndCountPojo.getSendCounts();

        //校验短信条数
        Integer smsCounts;
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("corpid", corpid);
        List<SmsConfigEntity> configLists = smsConfigModel.findEntitys(param);
        LOG.info("send ---> configLists" + configLists);
        if (configLists.size() == 0) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, "没有可用的短信签名！");
        }
        SmsConfigEntity confEntity = configLists.get(0);
        smsCounts = confEntity.getSmsCount();
        smsCounts = (smsCounts == null) ? Integer.valueOf(0) : smsCounts;
        if (sendCounts > smsCounts) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, "短信额度不足！");
        }
        LOG.info("send ---> smsCounts" + smsCounts);

        // 短信消费发送
        smsSend(statusLists, sendType, sendTime);

        addDynamic(statusLists, smsRabbitMqDTO.getCorpid(), smsRabbitMqDTO.getBusinessType());
    }

    /**
     * 客户或联系人列表发送短信
     *
     * @param smsRabbitMqDTO 入参
     * @return
     * @throws XbbException
     * @author youli.chen
     * @date: 2019-01-25 19:46
     * @version v1.0
     * @since v1.0
     */
    @Override
    public void sendForBusiness(SmsRabbitMqDTO smsRabbitMqDTO) throws XbbException {
        String corpid = smsRabbitMqDTO.getCorpid();
        String userId = smsRabbitMqDTO.getUserId();

        String sender = "";
        if (Objects.equals(PaasConstant.SYS_USER_ID, userId)) {
            sender = I18nMessageUtil.getMessage(PaasConstant.SYS_GENERATED);
        } else {
            UserEntity userEntity = userModel.getByKey(userId, corpid);
            if (userEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004);
            }
            sender = userEntity.getName();
        }
        // 短信发送类型
        Integer sendType = smsRabbitMqDTO.getSendType();
        if (sendType == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信发送类型不能为空");
        }
        List<Integer> sendTypeList = Arrays.asList(SmsSendTypeEnum.AT_ONCE.getCode(), SmsSendTypeEnum.DELAY.getCode());
        if (!sendTypeList.contains(sendType)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, "短信发送类型只能选即时发送或定时发送");
        }

        // 短信发送时间
        String dates = smsRabbitMqDTO.getDates();
        long sendTime = checkSendTime(sendType, dates);
        List<Long> sendDatas = smsRabbitMqDTO.getDataIdList();
        if (sendDatas == null || sendDatas.size() == 0) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信接收人不能为空");
        }
        // 去重
        HashSet<Long> h = new HashSet<>(sendDatas);
        sendDatas = new ArrayList<>(h);

        // 获取需要发送短信的列表以及条数
        SmsListAndCountPojo smsListAndCountPojo = new SmsListAndCountPojo();
        smsListAndCount(smsListAndCountPojo, smsRabbitMqDTO, sender, corpid, userId, sendDatas, sendType);
        List<SmsStatusEntity> statusLists = smsListAndCountPojo.getStatusLists();
        Integer sendCounts = smsListAndCountPojo.getSendCounts();

        //校验短信条数
        Integer smsCounts;
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("corpid", corpid);
        List<SmsConfigEntity> configLists = smsConfigModel.findEntitys(param);
        if (configLists.size() > 0) {
            SmsConfigEntity confEntity = configLists.get(0);
            smsCounts = confEntity.getSmsCount();
            if (null == smsCounts) {
                smsCounts = 0;
            }
            if (sendCounts > smsCounts) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, "短信额度不足！");
            }
        } else {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, "后台数据错误，请重试！");
        }

        // 短信消费发送
        smsSend(statusLists, sendType, sendTime);

        if (Objects.equals(SmsSendTypeEnum.AT_ONCE.getCode(), sendType)) {
            addDynamic(statusLists, smsRabbitMqDTO.getCorpid(), smsRabbitMqDTO.getBusinessType());
        }
    }

    @Override
    public SmsImportExcelResultVO importExcelResult(SmsImportExcelResultDTO smsImportExcelResultDTO) throws XbbException {
        SmsImportExcelResultVO smsImportExcelResultVO = new SmsImportExcelResultVO();
        try {
            String corpid = smsImportExcelResultDTO.getCorpid();

            // 获取缓存数据
            String importResultRedis = paasRedisHelper.getValue(RedisPrefixConstant.SMS_RECEIVER_IMPORT_RESULT, corpid);
            List<SmsImportExcelResultPojo> importPojoList;
            try {
                importPojoList = JSONArray.parseArray(importResultRedis, SmsImportExcelResultPojo.class);
            } catch (Exception e) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "解析导入短信接收人失败");
            }

            smsImportExcelResultVO.setList(importPojoList);

        } catch (Exception e) {
            LOG.error("获取导入短信接收人失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return smsImportExcelResultVO;
    }

    @Override
    public SmsCancelSendVO cancelSend(SmsCancelSendDTO smsCancelSendDTO) throws XbbException {
        SmsCancelSendVO smsCancelSendVO = new SmsCancelSendVO();

        String corpid = smsCancelSendDTO.getCorpid();
        String userId = smsCancelSendDTO.getUserId();

        boolean nonSenderFlag = false;
        // 短信记录id列表
        List<Long> smsIdIn = smsCancelSendDTO.getSmsIdIn();
        if (smsIdIn.size() == 0) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, "短信记录id不能为空");
        }

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("idIn", smsIdIn);
        param.put("corpid", corpid);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("type", SmsSendTypeEnum.DELAY.getCode());
        param.put("status", SmsStatusEnum.NO_SEND.getCode());

        try {

            List<SmsStatusEntity> smsList = smsStatusModel.getByIdIn(param);
            for (SmsStatusEntity entity : smsList) {
                if (!userId.equals(entity.getUserId())) {
                    nonSenderFlag = true;
                    break;
                }
            }

            if (nonSenderFlag) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "非自己发送的短信不可取消");
            }

            param.clear();
            param.put("idIn", smsIdIn);
            param.put("corpid", corpid);
            // 修改短信状态，和del标识
            param.put("status", SmsStatusEnum.CANCEL_SEND.getCode());
            smsStatusModel.cancelByIdIn(param);

        } catch (Exception e) {
            LOG.error("取消发送定时短信失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return smsCancelSendVO;
    }

    /**
     * 重发短信
     *
     * @param smsRabbitMqDTO 入参
     * @return
     * @throws XbbException
     * @author youli.chen
     */
    @Override
    public void resend(SmsRabbitMqDTO smsRabbitMqDTO) throws XbbException {
        String corpid = smsRabbitMqDTO.getCorpid();
        String userId = smsRabbitMqDTO.getUserId();
        UserEntity userEntity = userModel.getByKey(userId, corpid);
        if (userEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004);
        }

        List<Long> smsIdIn = smsRabbitMqDTO.getSmsIdIn();
        if (smsIdIn == null || smsIdIn.size() == 0) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信id不能为空");
        }

        // 重发条件：发送成功，发送失败
        List<Integer> statusIn = Arrays.asList(SmsStatusEnum.SUCCESS_SEND.getCode(), SmsStatusEnum.FAILURE_SEND.getCode());
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("idIn", smsIdIn);
        param.put("corpid", corpid);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("statusIn", statusIn);
        List<SmsStatusEntity> smsList = smsStatusModel.getByIdIn(param);

        List<SmsStatusEntity> newSmsList = new ArrayList<>();
        if (smsList != null && smsList.size() > 0) {
            for (SmsStatusEntity entity : smsList) {
                entity.setStatus(SmsStatusEnum.RE_SEND.getCode());

                SmsStatusEntity newEntity = new SmsStatusEntity();
                BeanUtil.copyProperties(entity, newEntity);

                newEntity.setSender(userEntity.getName());
                newEntity.setUserId(userId);
                /*
                 * 定时发送，重新发送的也变成即时发送
                 */
                newEntity.setType(SmsSendTypeEnum.AT_ONCE.getCode());
                newEntity.setStatus(SmsStatusEnum.NO_SEND.getCode());
                newSmsList.add(newEntity);
            }

            param.clear();
            param.put("idIn", smsIdIn);
            param.put("corpid", corpid);
            param.put("status", SmsStatusEnum.RE_SEND.getCode());
            smsStatusModel.updateBatchForStatus(param);

            smsStatusModel.insertBatch(newSmsList);
            for (SmsStatusEntity newEntity : newSmsList) {
                // 创蓝消费短信
                send(newEntity);
            }

            addDynamic(newSmsList, corpid, smsRabbitMqDTO.getBusinessType());
        }
    }


    @Override
    public SmsLogListVO logList(SmsLogListDTO smsLogListDTO) throws XbbException {
        SmsLogListVO smsLogListVO = new SmsLogListVO();
        try {
            String corpid = smsLogListDTO.getCorpid();
            String userId = smsLogListDTO.getUserId();
            UserEntity userEntity = userModel.getByKey(userId, corpid);
            if (userEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004, SystemErrorCodeEnum.API_ERROR_100004.getMsg());
            }

            // 查询条件
            Integer refType = smsLogListDTO.getRefType();
            String mobileLike = smsLogListDTO.getMobileLike();
            String receiverLike = smsLogListDTO.getReceiverLike();
            String senderLike = smsLogListDTO.getSenderLike();
            String contentLike = smsLogListDTO.getContentLike();
            Integer status = smsLogListDTO.getStatus();
            List<String> timeSpan = smsLogListDTO.getTimeSpan();

            mobileLike = mobileLike != null ? mobileLike.trim() : null;
            receiverLike = receiverLike != null ? receiverLike.trim() : null;
            senderLike = senderLike != null ? senderLike.trim() : null;
            contentLike = contentLike != null ? contentLike.trim() : null;
            Integer startTimeF = null;
            Integer endTimeF = null;
            if (timeSpan != null && timeSpan.size() != 0) {
                startTimeF = DateUtil.getInt(timeSpan.get(0), DateUtil.SDFDate);
                endTimeF = DateUtil.getInt(timeSpan.get(1), DateUtil.SDFDate) + RedisConstant.LONG_DURATION;
            }

            boolean maxDatePermission = userModel.isBoss(userEntity);
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

            //老板管理员看全部人,其余看自己
            if (!maxDatePermission) {
                param.put("userId", userId);
            }

            param.put("del", DelEnum.NORMAL.getDel());
            param.put("corpid", corpid);
            param.put("refType", refType);
            CommentUtil.addToMap(param,"mobileLike", mobileLike);
            CommentUtil.addToMap(param,"receiverLike", receiverLike);
            CommentUtil.addToMap(param,"senderLike", senderLike);
            CommentUtil.addToMap(param,"contentLike", contentLike);
            param.put("startTime", startTimeF);
            param.put("endTime", endTimeF);
            param.put("status", status);
            param.put("orderByStr", "add_time desc");
            param.put("page", smsLogListDTO.getPage());

            PageHelper pageHelper = PageHelperUtil.getPageHelper(param, smsStatusModel, smsLogListDTO.getPageSize());
            List<SmsStatusEntity> list = (List<SmsStatusEntity>) PageHelperUtil.getEntityList(param, pageHelper, smsStatusModel);
            List<SmsLogPojo> resultList = new ArrayList<>();
            for (SmsStatusEntity entity : list) {
                String sendTime = null;
                if (entity.getSendTime() != null) {
                    sendTime = DateUtil.getString(entity.getSendTime() * 1000, SDFYMDHM);
                }
                SmsStatusEnum statusEnum = SmsStatusEnum.getByCode(entity.getStatus());
                String statusName = statusEnum == null ? "" : statusEnum.getName();
                // 未发送且定时发送消息,且只能是自己发送的短信
                boolean cancelBtn = entity.getStatus() == SmsStatusEnum.NO_SEND.getCode() &&
                        entity.getType() == SmsSendTypeEnum.DELAY.getCode() && userId.equals(entity.getUserId());
                // 发送失败展示重发按钮
                boolean resendBtn = Objects.equals(entity.getStatus(), SmsStatusEnum.FAILURE_SEND.getCode());

                String refName = "";
                if(entity.getRefType() != null){
                    SmsModuleTypeEnum smsModuleTypeEnum = SmsModuleTypeEnum.getByCode(entity.getRefType());
                    refName = smsModuleTypeEnum == null ? "" : smsModuleTypeEnum.getName();
                }

                SmsLogPojo pojo = new SmsLogPojo();
                BeanUtil.copyProperties(entity, pojo);
                pojo.setSmsId(entity.getId());
                pojo.setRefTypeName(refName);
                pojo.setSendTime(sendTime);
                pojo.setStatusName(statusName);
                pojo.setCancelBtn(cancelBtn);
                pojo.setResendBtn(resendBtn);
                SmsExplainPojo smsExplainPojo = new SmsExplainPojo();
                smsExplainPojo.setDataId(entity.getRefId());
                smsExplainPojo.setAppId(entity.getAppId());
                smsExplainPojo.setMenuId(entity.getMenuId());
                smsExplainPojo.setFormId(entity.getFormId());
                smsExplainPojo.setBusinessType(entity.getRefType());
                smsExplainPojo.setSubBusinessType(entity.getRefType());
                smsExplainPojo.setSaasMark(entity.getSaasMark());
                pojo.setEntity(smsExplainPojo);
                pojo.setJump(entity.getRefId() == null ? false : true);
                resultList.add(pojo);
            }

            smsLogListVO.setPageHelper(pageHelper);
            smsLogListVO.setList(resultList);

        } catch (Exception e) {
            LOG.error("短信记录列表失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return smsLogListVO;
    }

    @Override
    public SmsLogStatisticVO logStatistic(SmsLogStatisticDTO smsLogStatisticDTO) throws XbbException {
        SmsLogStatisticVO smsLogStatisticVO = new SmsLogStatisticVO();
        String corpid = smsLogStatisticDTO.getCorpid();
        String userId = smsLogStatisticDTO.getUserId();
        UserEntity userEntity = userModel.getByKey(userId, corpid);
        if (userEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004, SystemErrorCodeEnum.API_ERROR_100004.getMsg());
        }
        try {
            Map<String, Object> param = new HashMap<>(16);

            param.put("del", DelEnum.NORMAL.getDel());
            param.put("corpid", corpid);

            boolean isBoss = userModel.isBoss(userEntity);
            //老板管理员看全部人统计,其余看自己的统计
            if (!isBoss) {
                param.put("userId", userId);
            }

            // 短信总数
            Integer counts = 0;
            // 待发送数
            Integer waitCounts = 0;
            // 正发送数
            Integer sendCounts = 0;
            // 发送成功数
            Integer successCounts = 0;
            // 发送失败数
            Integer failCounts = 0;
            // 取消发送数
            Integer cancelCounts = 0;
            List<Integer> statusIn = Arrays.asList(SmsStatusEnum.NO_SEND.getCode(), SmsStatusEnum.SEND_ING.getCode(),
                    SmsStatusEnum.SUCCESS_SEND.getCode(), SmsStatusEnum.FAILURE_SEND.getCode(),
                    SmsStatusEnum.CANCEL_SEND.getCode(), SmsStatusEnum.RE_SEND.getCode());
            param.put("statusIn", statusIn);
            List<Map<String, Object>> statusInList = smsStatusModel.getCountByStatusIn(param);
            if (statusInList.size() != 0) {
                int resendCount = 0;
                for (Map<String, Object> map : statusInList) {
                    Integer status = (Integer) map.get("status");
                    Long count = (Long) map.get("count");
                    SmsStatusEnum statusEnum = SmsStatusEnum.getByCode(status.intValue());
                    switch (statusEnum) {
                        case NO_SEND:
                            waitCounts = count.intValue();
                            break;
                        case SEND_ING:
                            sendCounts = count.intValue();
                            break;
                        case SUCCESS_SEND:
                            successCounts = count.intValue();
                            break;
                        case FAILURE_SEND:
                            failCounts = count.intValue();
                            break;
                        case CANCEL_SEND:
                            cancelCounts = count.intValue();
                            break;
                        case RE_SEND:
                            resendCount = count.intValue();
                            break;
                        default:
                            break;
                    }
                    counts = waitCounts + sendCounts + successCounts + failCounts + cancelCounts + resendCount;
                }
            }


            smsLogStatisticVO.setCounts(counts);
            smsLogStatisticVO.setWaitCounts(waitCounts);
            smsLogStatisticVO.setSendCounts(sendCounts);
            smsLogStatisticVO.setSuccessCounts(successCounts);
            smsLogStatisticVO.setFailCounts(failCounts);
            smsLogStatisticVO.setCancelCounts(cancelCounts);
        } catch (Exception e) {
            LOG.error("获取短信记录统计失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return smsLogStatisticVO;
    }

    /**
     * 通过crontab定时任务每十分钟不停的拉取并更新短信状态
     *
     * @param updateStatusDTO 入参
     * @return
     * @author youli.chen
     * @version
     * @since
     */
    @Override
    public SmsUpdateStatusVO cronTabUpdateStatus(SmsUpdateStatusDTO updateStatusDTO) throws XbbException {
        SmsUpdateStatusVO smsUpdateStatusVO = new SmsUpdateStatusVO();
        String key = updateStatusDTO.getKey();
        if (!Objects.equals(key, BasicConstant.TASK_SECRET_KEY)) {
            LOG.error("短信定时发送任务脚本校验 密码错误，停止定时任务！");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100066);
        }

        updateSmsStatus(updateStatusDTO.getSendApi());

        return smsUpdateStatusVO;
    }

    /**
     * 短信定时任务脚本异步方法
     *
     * @param smsCronTabAsyncDTO 短信定时任务脚本入参
     * @return Integer
     * @throws XbbException 业务异常
     * @version v1.0
     * @since v1.0
     */
    @Override
    @Async(value = "updateSmsStatusThreadPool")
    public void updateSmsStatusAsync(SmsCronTabAsyncDTO smsCronTabAsyncDTO) throws XbbException {
        String[] split = smsCronTabAsyncDTO.getLocale().split("_");
        LocaleContextHolder.setLocale(new Locale(split[0], split[1]));
        String corpid = smsCronTabAsyncDTO.getCorpid();
        boolean onlyCorpId = true;

        List<CompanyEntity> companyList;
        // 针对一家公司发送短信
        if (StringUtil.isNotEmpty(corpid)) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put("corpid", corpid);
            params.put("start", 0);
            params.put("pageNum", 1);
            companyList = companyModel.findEntitys(params);
            if (companyList.size() > 0) {
                smsCronTabStatus(corpid, onlyCorpId);
                LOG.info("公司（ID=" + companyList.get(0).getCorpid() + "）：更新短信状态任务执行完成！");
                LOG.info("updateSmsStatus_finished:" + companyList.get(0).getCorpid());
            }
        } else {
            try {
                // 定时任务每隔一分钟执行：查询出1000条需要定时发送的短信
                onlyCorpId = false;
                smsCronTabStatus(corpid, onlyCorpId);
            }catch (Exception e){
                LOG.error("updateSmsStatus:for_company 循环的时候出现了奇怪的异常", e);
            }
        }
    }

    /**
     * 查询短信余额,并进行预警
     *
     * @throws XbbException
     * @author youli.chen
     * @date: 2019-01-25 19:45
     * @version 1.0
     * @since v1.0
     */
    @Override
    public void getBalance() throws XbbException {
        SmsSpacePojo smsSpacePojo = new SmsSpacePojo();
        // 获取通知类账户余额
        smsSpacePojo = SMSSpaceService.getNoticeBalance();
        if(Objects.equals(smsSpacePojo.getSmsStatus(), "success")){
            if(Integer.valueOf(smsSpacePojo.getSmsCode()) < 10000){
                String content = "亲爱的管理员您好，pro系统短信通知类短信余额为："+ smsSpacePojo.getSmsCode() +"条，额度已经不足1万条，请及时充值。";
                SMSSpaceService.sendNoticeSMS(SMSSpaceService.XBB_MASTER_MOBILE, content, "");
            }
        }
        // 获取营销类账户余额
        smsSpacePojo = SMSSpaceService.getMarketBalance();
        if(Objects.equals(smsSpacePojo.getSmsStatus(), "success")){
            if(Integer.valueOf(smsSpacePojo.getSmsCode()) < 10000){
                String content = "亲爱的管理员您好，pro系统短信营销类短信余额为："+ smsSpacePojo.getSmsCode() +"条，额度已经不足1万条，请及时充值。";
                SMSSpaceService.sendNoticeSMS(SMSSpaceService.XBB_MASTER_MOBILE, content, "");
            }
        }
    }

    /**
     * 定时发送：空间畅想短信定时发送任务，每天0点0分0秒到目前时间
     * @param corpid
     * @throws XbbException
     */
    private void smsCronTabStatus(String corpid, boolean onlyCorpId) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", DelEnum.NORMAL.getDel());
        // 未发送
        param.put("status", 0);
        // 定时发送
        param.put("type", 1);
        // 每天0点0分0秒到目前时间的定时短信(主要是考虑到服务器重启造成的时间空白，进行容错)
        Integer now = DateUtil.getInt();
        Integer startTime = DateUtil.getTodayInt();
        Integer endTime = now;
        param.put("startTime", startTime);
        param.put("endTime", endTime);
        if(!onlyCorpId){
            param.put("start", 0);
            param.put("pageNum", 1000);
        }
        List<SmsStatusEntity> lists = smsStatusModel.findEntitys(param);
        if (CollectionsUtil.isEmpty(lists)) {
            return;
        }
        boolean isGrayEnvironmentEnable = sysEnvHelp.isGrayEnvironmentEnable();

        // 获取短信配置，请限制corpid数量，超过1000条分页
        List<String> corpidList = lists.stream().map(SmsStatusEntity::getCorpid).distinct().collect(Collectors.toList());
        Map<String, Object> smsConfigParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        smsConfigParam.put("corpidIn", corpidList);
        smsConfigParam.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        List<SmsConfigEntity> smsConfigList = smsConfigModel.findEntitys(smsConfigParam);
        Map<String, Integer> consumerCountMap = new HashMap<>(corpidList.size());

        List<SmsStatusEntity> updateList = new ArrayList<>();
        // 轮询发送
        for(SmsStatusEntity entity : lists){

            if (sysEnvHelp.isGrayEnvironment()) {
                if (!isGrayEnvironmentEnable) {
                    return ;
                }
                if (!sysEnvHelp.checkIsCrayCompany(entity.getCorpid())) {
                    return;
                }
            } else {
                if (isGrayEnvironmentEnable) {
                    if (sysEnvHelp.checkIsCrayCompany(entity.getCorpid())) {
                        return;
                    }
                }
            }

//            send(entity);
            SmsSpacePojo ret = send2Space(entity);
            if (Objects.isNull(ret)) {
                continue;
            }
            int count = getConsumerCount(ret, entity);
            setSmsStatusEntity(entity, ret.getSmsCode(), ret.getSmsMsg(), count);
            updateList.add(entity);
            int curCount = consumerCountMap.getOrDefault(entity.getCorpid(), BasicConstant.ZERO);
            consumerCountMap.put(entity.getCorpid(), curCount + count);
        }

        // 更新短信配置及短信状态
        List<SmsConfigEntity> updateConfigList = new ArrayList<>();
        for (SmsConfigEntity configEntity : smsConfigList) {
            if (!consumerCountMap.containsKey(configEntity.getCorpid())) {
                continue;
            }
            int count = consumerCountMap.get(configEntity.getCorpid());
            if (count == BasicConstant.ZERO) {
                continue;
            }
            setSmsConfigEntity(configEntity, count);
            updateConfigList.add(configEntity);
        }
        smsConfigModel.updateBatch(updateConfigList);
        smsStatusModel.updateBatch(updateList);

        addDynamic(lists, corpid, XbbRefTypeEnum.UNKNOWN.getCode());
    }

    /**
     * 更新短信状态
     * @param sendApi
     * @throws XbbException
     */
    private void updateSmsStatus(Integer sendApi) throws XbbException {
        List<SmsPullPojo> retList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (Objects.equals(sendApi, SmsTemplateSendApiEnum.SPACE_IMAGINATION_MARKET_AMOUNT.getCode())) {
            // 4：空间畅想营销账号
            retList = SMSSpaceService.getMarketMsg();
        } else if (Objects.equals(sendApi, SmsTemplateSendApiEnum.SPACE_IMAGINATION_NOTICE_AMOUNT.getCode())) {
            // 3：空间畅想通知账号
            retList = SMSSpaceService.getNoticeMsg();
        }
        Integer count = retList.size();
        if(Objects.equals(0, count)) {
            return;
        }

        for (SmsPullPojo smsPullPojo : retList) {
            String msgId = smsPullPojo.getSmsNo();
            String status = smsPullPojo.getSmsReport();

            try {
                LOG.info("--------开始更新短信---------："+ msgId);
                querySendStatus(msgId, status);
                LOG.info("--------结束更新短信---------："+ msgId);
            } catch (XbbException e) {
                e.printStackTrace();
                LOG.error("获取短信状态回调失败", e);
            }
        }

        // 超过1000条，再次查询
        if(count > SMSSpaceService.MAX_PULL_NUM) {
            updateSmsStatus(sendApi);
        }
    }

    /**
     * 更新短信状态
     *
     * @param msgId      短信编号
     * @param statusCode 空间畅想提供的短信状态
     * @throws XbbException
     */
    private void querySendStatus(String msgId, String statusCode) throws XbbException {
        String statusMemo = "";
        int status = SmsStatusEnum.FAILURE_SEND.getCode();
        if(statusCode.contains("%3A")){
            statusCode = statusCode.replace("%3A",":");
        }
        switch (statusCode) {
            case "DELIVRD":
                status = SmsStatusEnum.SUCCESS_SEND.getCode();
                statusMemo = "短消息转发成功";
                break;
            case "EXPIRED":
                statusMemo = "短消息超过有效期";
                break;
            case "UNDELIV":
                statusMemo = "短消息是不可达的";
                break;
            case "UNKNOWN":
                statusMemo = "未知短消息状态";
                break;
            case "REJECTD":
                statusMemo = "短消息被短信中心拒绝";
                break;
            case "DTBLACK":
                statusMemo = "目的号码是黑名单号码";
                break;
            case "ERR:104":
                statusMemo = "系统忙";
                break;
            case "REJECT":
                statusMemo = "审核驳回";
                break;
            case "BLACK":
                statusMemo = "运营商设定为黑名单";
                break;
            case "E:RPTSD":
                statusMemo = "禁止同一号码发送同一内容";
                break;
            case "MK:100D":
                statusMemo = "黑名单";
                break;
            case "MN:0001":
                statusMemo = "空号";
                break;
            case "YX:9006":
                statusMemo = "运营商选不到通道";
                break;
            default:
                statusMemo = "网关内部状态";
                break;
        }
        try {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("msgId", msgId);
            List<SmsStatusEntity> lists = smsStatusModel.findEntitys(param);
            long statusTime = DateUtil.getInt();
            if (lists.size() > 0) {
                SmsStatusEntity entity = lists.get(0);
                entity.setStatus(status);
                entity.setStatusCode(statusCode);
                entity.setStatusMemo(statusMemo);
                entity.setStatusTime(statusTime);
                smsStatusModel.update(entity);

                // 短信条数返回
                if (!Objects.equals(status, SmsStatusEnum.SUCCESS_SEND.getCode())) {
                    backSmsFee(entity.getCorpid(), entity.getContent());
                }
            } else {
                // 数据有问题
                LOG.error("空间畅想回调数据与库中数据不符，msgid:" + msgId);
            }
        } catch (Exception e) {
            LOG.error("记录下当前的msgId和statusCode:" + msgId, statusCode);
            LOG.error("获取短信状态回调失败", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    /**
     * 补偿退回短信条数
     * @param corpid
     * @param content
     */
    private void backSmsFee(String corpid, String content){
        Integer counts = 1;
        if (content.length() > SmsSetConstant.SMS_MAX_LENGTH) {
            /*
             * 长短信67字一条,防止整除时多加1
             */
            counts = content.length() / SmsSetConstant.SMS_REAL_LENTTH;
            counts += (content.length() % SmsSetConstant.SMS_REAL_LENTTH == 0) ? 0 : 1;
        }
        Map<String, Object> param = new HashMap<>(16);
        param.put("del", DelEnum.NORMAL.getDel());
        param.put("corpid", corpid);
        param.put("start", 0);
        param.put("pageNum", 1);

        SmsConfigEntity configEntity = smsConfigModel.findEntitys(param).get(0);
        Integer smsCount = configEntity.getSmsCount();
        Integer sentCount = configEntity.getSentCount();
        if (null == sentCount) {
            sentCount = 0;
        }
        smsCount += counts;
        sentCount -= counts;
        configEntity.setSmsCount(smsCount);
        Double smsBalance = configEntity.getSmsBalance() == null ? 0D : configEntity.getSmsBalance() + counts * 0.05;
        configEntity.setSmsBalance(smsBalance);
        configEntity.setSentCount(sentCount);
        smsConfigModel.update(configEntity);
    }
    /**
     * 短信数据封装 获取短信需要的电话和姓名
     *
     * @param smsRabbitMqDTO 业务列表页发送短信入参
     * @param corpid         公司ID
     * @param sendDatas      需要发送ID(客户或联系人)
     * @throws XbbException
     */
    private void smsHashMap(SmsRabbitMqDTO smsRabbitMqDTO,
                            String corpid, List<Long> sendDatas) throws XbbException {
        Integer refType = smsRabbitMqDTO.getBusinessType();
        if (refType == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, ErrorMessageConstant.BUSINESS_TYPE_CANNOT_EMPTY);
        }

        Integer numberType = smsRabbitMqDTO.getNumberType();
        if (numberType == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "请选择号码发送方式");
        }

        List<SmsReceiverPojo> sendData = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        if (Objects.equals(refType, XbbRefTypeEnum.CONTACT.getCode())) {
            List<ContactEntityExt> contactEntityExtList = contactService.getContactListByIds(corpid, sendDatas);
            if (CollectionsUtil.isEmpty(contactEntityExtList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004, "查询不到需要发送的联系人名单");
            }
            for(ContactEntityExt contact : contactEntityExtList){
                JSONObject contactData = contact.getData();
                JSONArray contactPhoneArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(contactData, ContactEnum.PHONE.getAttr(), new JSONArray());
                if (CollectionsUtil.isEmpty(contactPhoneArray)) {
                    continue;
                }
                String name = FastJsonHelper.getStringOrDefaultFromFormData(contactData, ContactEnum.NAME.getAttr(), "");
                for (Object object : contactPhoneArray) {
                    String tel = getMobile(object);
                    if (!StringUtil.isMobile(tel, MapConstant.CHINA)) {
                        continue;
                    }

                    SmsReceiverPojo smsReceiverPojo = getSmsReceiverPojo(tel,contact,name,ContactEnum.PHONE.getAttr(),refType);
                    sendData.add(smsReceiverPojo);
                    if(Objects.equals(numberType, 4)){
                        break;
                    }
                }
            }
        }
        if (Objects.equals(refType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
            List<CustomerEntityExt> customerExtList = customerService.getCustomerListByIds(corpid, sendDatas);
            if (CollectionsUtil.isEmpty(customerExtList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004, "查询不到需要发送的客户名单");
            }
            List<Long> customerIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            customerExtList.forEach(customer -> customerIdIn.add(customer.getId()));
            if(Objects.equals(numberType, 1)){
                // 查询客户的主联系人
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termQuery("data." + ContactEnum.IS_MAIN.getAttr(), 1));
                boolQueryBuilder.filter(termsQuery(ContactEnum.getEsAttr4Keyword(ContactEnum.CUSTOMER_NAME),customerIdIn));
                List<String> contactFieldList = Arrays.asList(FieldTypeEnum.DATAID.getAlias(), StringConstant.JSON_DATA);
                List<PaasFormDataEntityExt> paasFormDataEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT,boolQueryBuilder,PaasFormDataEntityExt.class, contactFieldList);
                if (CollectionsUtil.isNotEmpty(paasFormDataEntityList)) {
                    for(PaasFormDataEntityExt contact : paasFormDataEntityList){
                        JSONObject contactData = contact.getData();
                        JSONArray contactPhoneArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(contactData, ContactEnum.PHONE.getAttr(), new JSONArray());
                        if (CollectionsUtil.isEmpty(contactPhoneArray)) {
                            continue;
                        }
                        String name = FastJsonHelper.getStringOrDefaultFromFormData(contactData, ContactEnum.NAME.getAttr(), "");
                        StringBuffer ownerName = getCustomerOwnerNameByDataId(corpid, contact.getDataId());
                        for (Object object : contactPhoneArray) {
                            String tel = getMobile(object);
                            if (!StringUtil.isMobile(tel, MapConstant.CHINA)) {
                                continue;
                            }

                            SmsReceiverPojo smsReceiverPojo = getSmsReceiverPojo(tel, contact, name, ContactEnum.PHONE.getAttr(), refType);
                            smsReceiverPojo.setOwnerName(ownerName.toString());
                            sendData.add(smsReceiverPojo);
                        }
                    }
                }
            } else {
                for(CustomerEntityExt customer : customerExtList){
                    JSONObject customerData = customer.getData();
                    JSONArray customerPhoneArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(customerData, CustomerManagementEnum.PHONE.getAttr(), new JSONArray());
                    if (CollectionsUtil.isEmpty(customerPhoneArray)) {
                        continue;
                    }
                    String name = FastJsonHelper.getStringOrDefaultFromFormData(customerData, CustomerManagementEnum.NAME.getAttr(), "");
                    StringBuffer ownerName = getCustomerOwnerNameByDataId(corpid, customer.getDataId());
                    for (Object object : customerPhoneArray) {
                        String tel = getMobile(object);
                        if (!StringUtil.isMobile(tel, MapConstant.CHINA)) {
                            continue;
                        }

                        SmsReceiverPojo smsReceiverPojo = getSmsReceiverPojo(tel, customer, name, CustomerManagementEnum.PHONE.getAttr(), refType);
                        smsReceiverPojo.setOwnerName(ownerName.toString());
                        sendData.add(smsReceiverPojo);
                        if(Objects.equals(numberType, 2)){
                            break;
                        }
                    }
                }
            }
        }
        //线索支持发短信
        if(Objects.equals(refType,XbbRefTypeEnum.CLUE.getCode())){
            List<ClueEntityExt> clueEntities = clueModel.getByKeys(sendDatas,corpid);
            if(CollectionsUtil.isEmpty(clueEntities)){
                throw new XbbException(ClueErrorCodeEnum.API_ERROR_1110023);
            }

            for (ClueEntityExt clueEntityExt : clueEntities){
                JSONObject originData = clueEntityExt.getData();
                JSONArray phoneArray = originData.getJSONArray(ClueEnum.PHONE.getAttr());
                if (CollectionsUtil.isEmpty(phoneArray)) {
                    continue;
                }
                String name = FastJsonHelper.getStringOrDefaultFromFormData(originData, ClueEnum.COMPANY_NAME.getAttr(), "");
                StringBuffer ownerName = getClueOwnerNameByDataId(clueEntityExt.getCorpid(), clueEntityExt.getDataId());

                SmsReceiverPojo smsReceiverPojo;
                if(Objects.equals(numberType,BasicConstant.SEVEN)){
                    //获取线索的任意客户电话
                    int randomPhone = (int)(Math.random() * phoneArray.size());
                    String phone = getMobile(phoneArray.get(randomPhone));
                    if (StringUtil.isMobile(phone, MapConstant.CHINA)) {
                        smsReceiverPojo = getSmsReceiverPojo(phone,clueEntityExt,name,ClueEnum.PHONE.getAttr(),refType);
                        smsReceiverPojo.setOwnerName(ownerName.toString());
                        sendData.add(smsReceiverPojo);
                    }
                }else {
                    //获取线索的所有客户电话
                    for (Object phoneObj : phoneArray){
                        String phone = getMobile(phoneObj);
                        if (!StringUtil.isMobile(phone, MapConstant.CHINA)) {
                            continue;
                        }
                        smsReceiverPojo = getSmsReceiverPojo(phone,clueEntityExt,name,ClueEnum.PHONE.getAttr(),refType);
                        smsReceiverPojo.setOwnerName(ownerName.toString());
                        sendData.add(smsReceiverPojo);
                    }
                }
            }
        }
        smsRabbitMqDTO.setSendData(sendData);
    }

    /**
     * 获取电话字段值
     *
     * @param phone
     * @return
     */
    private String getMobile(Object phone) {
        JSONObject phoneJsonObject = (JSONObject) phone;
        return phoneJsonObject.getString(StringConstant.PHONE_TEL_ATTR);
    }

    /**
     * 拼接实体
     * @param phone
     * @param paasFormDataEntityExt
     * @param name
     * @param phoneAttr
     * @param refType
     * @return
     * @throws XbbException
     */
    private SmsReceiverPojo getSmsReceiverPojo(String phone,PaasFormDataEntityExt  paasFormDataEntityExt,String name,String phoneAttr,Integer refType) throws XbbException {
        SmsReceiverPojo smsReceiverPojo = new SmsReceiverPojo(name, phone, paasFormDataEntityExt.getId(), refType,
                paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getMenuId(), paasFormDataEntityExt.getFormId(), SaasMarkEnum.SAAS.getCode(), phoneAttr);
        return smsReceiverPojo;
    }

    /**
     * 获取需要发送短信的列表以及条数
     *
     * @param smsListAndCountPojo 短信条数以及列表
     * @param smsRabbitMqDTO      业务列表页发送短信入参
     * @param sender              发送人姓名
     * @param corpid              公司id
     * @param userId              用户ID
     * @param sendDatas           需要发送ID(客户或联系人)
     * @param sendType            发送类型:0即时发送，1定时发送
     * @throws XbbException
     */
    private void smsListAndCount(SmsListAndCountPojo smsListAndCountPojo, SmsRabbitMqDTO smsRabbitMqDTO,
                                 String sender, String corpid, String userId, List<Long> sendDatas,
                                 Integer sendType) throws XbbException {
        // 短信内容
        String content = smsRabbitMqDTO.getContent();
        if (content == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信内容不能为空");
        }
        String mobile;
        String receiver;
        // 获取这个模版该用什么方式发送，chb 20170616
        Integer sendApi = smsRabbitMqDTO.getSendApi();

        // 获取短信需要的电话和姓名
        //SmsHashMapPojo smsHashMapPojo = new SmsHashMapPojo();
        smsHashMap(smsRabbitMqDTO, corpid, sendDatas);

        List<SmsReceiverPojo> sendData = smsRabbitMqDTO.getSendData();

        List<SmsStatusEntity> statusLists = new ArrayList<>();
        int sendCounts = 0;
        for (int i = 0; i < sendData.size(); i++) {
            SmsReceiverPojo smsReceiverPojo = sendData.get(i);
            Long refId = smsReceiverPojo.getRefId();
            Integer refType = smsReceiverPojo.getRefType();
            Long appId = smsReceiverPojo.getAppId();
            Long menuId = smsReceiverPojo.getMenuId();
            Long formId = smsReceiverPojo.getFormId();
            Integer saasMark = smsReceiverPojo.getSaasMark();
            String attr = smsReceiverPojo.getAttr();
            String contentTemp = content;
            receiver = smsReceiverPojo.getName();
            String ownerName = smsReceiverPojo.getOwnerName();
            if (contentTemp.contains("{客户尊称}")) {
                contentTemp = contentTemp.replaceAll("\\{客户尊称\\}", receiver);
            }
            if (contentTemp.contains("{客户负责人}")) {
                contentTemp = contentTemp.replaceAll("\\{客户负责人\\}", ownerName);
            }
            if (contentTemp.contains("{线索负责人}")) {
                contentTemp = contentTemp.replaceAll("\\{线索负责人\\}", ownerName);
            }
            mobile = smsReceiverPojo.getPhone();
            mobile = StringUtil.isEmpty(mobile) ? "" : mobile;

            SmsStatusEntity entity = new SmsStatusEntity();
            entity.setCorpid(corpid);
            entity.setSender(sender);
            entity.setReceiver(receiver);
            entity.setMobile(mobile);
            entity.setUserId(userId);
            entity.setType(sendType);
            entity.setContent(contentTemp);
            entity.setStatus(0);
            entity.setSendApi(sendApi);
            long now = DateUtil.getInt();
            entity.setUpdateTime(now);
            entity.setAddTime(now);

            entity.setAttr(attr);
            entity.setRefId(refId);
            entity.setRefType(refType);
            entity.setAppId(appId);
            entity.setMenuId(menuId);
            entity.setFormId(formId);
            entity.setSaasMark(saasMark);
            statusLists.add(entity);

            //逐条计算发送条数：可能因可变字段长度条数不一致
            //每条短信分为几条
            Integer counts = 1;
            if (contentTemp.length() > 70) {
                counts = contentTemp.length() / 67;
                //长短信67字一条,防止整除时多加1
                counts += (contentTemp.length() % 67 == 0) ? 0 : 1;
            }
            sendCounts += counts;
        }


/*        for (Long sendId : sendDatas) {
            String contentTemp = content;
            receiver = idAndName.get(sendId);
            if (contentTemp.contains(SmsSetConstant.SMS_RECEIVER_PLACE_HOLDER)) {
                contentTemp = contentTemp.replaceAll("\\{客户尊称\\}", receiver);
            }
            mobile = idAndPhone.get(sendId);
            mobile = StringUtil.isEmpty(mobile) ? "" : mobile;

            JSONArray phoneArray;
            try {
                phoneArray = JSON.parseArray(mobile);
            } catch (Exception e) {
                phoneArray = new JSONArray();
            }
            if (phoneArray != null && phoneArray.size() != 0) {
                JSONObject phoneTmp = phoneArray.getJSONObject(0);
                mobile = phoneTmp.getString("text_2");
                mobile = StringUtil.isEmpty(mobile) ? "" : mobile;
            }
            SmsStatusEntity entity = new SmsStatusEntity();
            entity.setCorpid(corpid);
            entity.setSender(sender);
            entity.setReceiver(receiver);
            entity.setMobile(mobile);
            entity.setUserId(userId);
            entity.setType(sendType);
            entity.setContent(contentTemp);
            entity.setStatus(0);
            entity.setSendApi(sendApi);
            long now = DateUtil.getInt();
            entity.setUpdateTime(now);
            entity.setAddTime(now);

            statusLists.add(entity);

            //逐条计算发送条数：可能因可变字段长度条数不一致
            //每条短信分为几条
            Integer counts = 1;
            if (contentTemp.length() > 70) {
                counts = contentTemp.length() / 67;
                //长短信67字一条,防止整除时多加1
                counts += (contentTemp.length() % 67 == 0) ? 0 : 1;
            }
            sendCounts += counts;
        }*/
        smsListAndCountPojo.setSendCounts(sendCounts);
        smsListAndCountPojo.setStatusLists(statusLists);
    }

    /**
     * 发送短信接口获取需要发送短信的列表以及条数
     *
     * @param smsListAndCountPojo 短信条数以及列表
     * @param smsRabbitMqDTO      短信发送入参
     * @param corpid              公司id
     * @param userId              用户ID
     * @param sender              发送人姓名
     * @param sendType            发送类型:0即时发送，1定时发送
     */
    private void sendSmsListAndCount(SmsListAndCountPojo smsListAndCountPojo, SmsRabbitMqDTO smsRabbitMqDTO, String corpid,
                                     String userId, String sender, Integer sendType) throws XbbException {
        // 短信内容
        String content = smsRabbitMqDTO.getContent();
        Integer businessType = smsRabbitMqDTO.getBusinessType();
        if (content == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信内容不能为空");
        }
        LOG.info("sendSmsListAndCount ---> content" + content);

        // 短信接收人
        String mobile;
        String receiver;
        List<SmsReceiverPojo> receiverPojoList = smsRabbitMqDTO.getSendData();
        if (receiverPojoList == null || receiverPojoList.size() == 0) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信接收人不能为空");
        }
        LOG.info("sendSmsListAndCount ---> receiverPojoList" + receiverPojoList);

        // 获取这个模版该用什么方式发送，chb 20170616
        Integer sendApi = smsRabbitMqDTO.getSendApi();
        LOG.info("sendSmsListAndCount ---> sendApi" + sendApi);

        List<SmsStatusEntity> statusLists = new ArrayList<>();
        int sendCounts = 0;
        for (SmsReceiverPojo receiverPojo : receiverPojoList) {
            String contentTemp = content;
            receiver = receiverPojo.getName();
            mobile = receiverPojo.getPhone();
            // 手机号不存在不发送
            if (!StringUtil.isMobile(mobile, MapConstant.CHINA)) {
                continue;
            }
            if (StringUtil.isEmpty(receiver)) {
                receiver = mobile;
            }
            if (contentTemp.contains(I18nMessageUtil.getMessage(SmsSetConstant.SMS_RECEIVER_PLACE_HOLDER))) {
                contentTemp = contentTemp.replaceAll("\\{客户尊称\\}", receiver);
            }
            smsRabbitMqDTO.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            List<Long> customerFormIdList = getFormIdList(smsRabbitMqDTO, CustomerManagementEnum.OWNER_ID.getAttr());
            smsRabbitMqDTO.setBusinessType(XbbRefTypeEnum.CLUE.getCode());
            List<Long> clueFormIdList = getFormIdList(smsRabbitMqDTO, ClueEnum.OWNER_ID.getAttr());
            if (contentTemp.contains(I18nMessageUtil.getMessage(StringConstant.CUSTOMER_RELATEDPERSONNEL_MEMO_OWNER))) {
                StringBuffer customerOwnerName = getOverName(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), receiver, customerFormIdList);
                contentTemp = contentTemp.replaceAll("\\{" + I18nMessageUtil.getMessage(StringConstant.CUSTOMER_RELATEDPERSONNEL_MEMO_OWNER) + "\\}", customerOwnerName.toString());
            }
            if (contentTemp.contains(I18nMessageUtil.getMessage(StringConstant.CLUE_RELATEDPERSONNEL_MEMO_OWNER))) {
                StringBuffer clueOwnerName = getOverName(corpid, XbbRefTypeEnum.CLUE.getCode(), receiver, clueFormIdList);
                contentTemp = contentTemp.replaceAll("\\{" + I18nMessageUtil.getMessage(StringConstant.CLUE_RELATEDPERSONNEL_MEMO_OWNER) + "\\}", clueOwnerName.toString());
            }
            SmsStatusEntity entity = new SmsStatusEntity(corpid, sender, receiver, mobile, userId,
                    sendType, contentTemp, SmsStatusEnum.NO_SEND.getCode(), sendApi);
            entity.setRefId(receiverPojo.getRefId());
            entity.setRefType(receiverPojo.getRefType());
            entity.setAppId(receiverPojo.getAppId());
            entity.setFormId(receiverPojo.getFormId());
            entity.setMenuId(receiverPojo.getMenuId());
            entity.setSaasMark(receiverPojo.getSaasMark());
            entity.setAttr(receiverPojo.getAttr());
            statusLists.add(entity);
            /*
             * 逐条计算发送条数：可能因可变字段长度条数不一致
             * 每条短信分为几条
             */
            Integer counts = 1;
            if (contentTemp.length() > SmsSetConstant.SMS_MAX_LENGTH) {
                counts = contentTemp.length() / SmsSetConstant.SMS_REAL_LENTTH;
                counts += (contentTemp.length() % SmsSetConstant.SMS_REAL_LENTTH == 0) ? 0 : 1;
            }
            sendCounts += counts;
        }
        LOG.info("sendSmsListAndCount ---> statusLists" + statusLists);
        LOG.info("sendSmsListAndCount ---> sendCounts" + sendCounts);

        smsListAndCountPojo.setStatusLists(statusLists);
        smsListAndCountPojo.setSendCounts(sendCounts);
    }

    /**
     * 对接创蓝进行短信消费
     *
     * @param smsStatusEntity 短信实体
     * @author youli.chen
     * @time 2017-6-16 上午11:07:25
     * 修改时间： 2018-1-5 上午10:16:35 chy
     * @version v1.0
     * @since 很早以前
     */
    private void send(SmsStatusEntity smsStatusEntity) throws XbbException {
        String corpid = smsStatusEntity.getCorpid();
        String mobile = smsStatusEntity.getMobile();
        String content = smsStatusEntity.getContent();
        Integer sendApi = smsStatusEntity.getSendApi();
        if (sendApi == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "营销帐号不能为空！");
        }
        if (Objects.equals(smsStatusEntity.getStatus(), SmsStatusEnum.SEND_ING.getCode())) {
            //短信为已发送状态，不再发送短信
            LOG.error("短信重复发送，被我阻止！记录实体id : ", smsStatusEntity.getId());
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, "短信重复发送，被我阻止！");
        }

        SmsTemplateSendApiEnum sendApiEnum = SmsTemplateSendApiEnum.getByCode(sendApi);
        if(Objects.isNull(sendApiEnum)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "营销帐号不存在！");
        }

        switch (sendApiEnum) {
            // pro暂时全部使用这个由空间畅想v8提供的短信服务
            case SPACE_IMAGINATION_MARKET_AMOUNT:
                // 空间畅想营销账号
                SmsSpacePojo smsPojo = SMSSpaceService.sendMarketSMS(mobile, content, corpid);
                // 处理短信返回状态入库
                dealSpaceRet(smsPojo, smsStatusEntity);
                break;
            case SPACE_IMAGINATION_NOTICE_AMOUNT:
                // 空间畅想通知账号
                SmsSpacePojo smsSpacePojo = SMSSpaceService.sendNoticeSMS(mobile, content, corpid);
                // 处理短信返回状态入库
                dealSpaceRet(smsSpacePojo, smsStatusEntity);
                break;
            case NEW_MARKET_AMOUNT:
                // 创蓝营销账号
                JSONObject marketRetJson = SMSMarketService.sendSMS(mobile, content);
                // 处理短信返回状态入库
                dealJsonRet(marketRetJson, smsStatusEntity);
                break;
            case CHUANG_LAN_NOTICE_AMOUNT:
                // 创蓝通知账号
                JSONObject noticeRetJson = SMSNoticeService.sendSMS(mobile, content);
                // 处理短信返回状态入库
                dealJsonRet(noticeRetJson, smsStatusEntity);
                break;
            case CHUANG_LAN_MARKET_AMOUNT:
            default:
                LOG.error("短信发送sendApi:case 0已经终止服务 : ", sendApi);
        }
    }

    /**
     * 发送短信，返回发送状态
     *
     * @param smsStatusEntity
     * @return
     * @throws XbbException
     */
    private SmsSpacePojo send2Space(SmsStatusEntity smsStatusEntity) throws XbbException {
        String corpid = smsStatusEntity.getCorpid();
        String mobile = smsStatusEntity.getMobile();
        String content = smsStatusEntity.getContent();
        Integer sendApi = smsStatusEntity.getSendApi();
        if (sendApi == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "营销帐号不能为空！");
        }
        if (Objects.equals(smsStatusEntity.getStatus(), SmsStatusEnum.SEND_ING.getCode())) {
            //短信为已发送状态，不再发送短信
            LOG.error("短信重复发送，被我阻止！记录实体id : ", smsStatusEntity.getId());
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, "短信重复发送，被我阻止！");
        }

        SmsTemplateSendApiEnum sendApiEnum = SmsTemplateSendApiEnum.getByCode(sendApi);
        if(Objects.isNull(sendApiEnum)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "营销帐号不存在！");
        }
        SmsSpacePojo smsSpacePojo;
        switch (sendApiEnum) {
            // pro暂时全部使用这个由空间畅想v8提供的短信服务
            case SPACE_IMAGINATION_MARKET_AMOUNT:
                // 空间畅想营销账号
                smsSpacePojo = SMSSpaceService.sendMarketSMS(mobile, content, corpid);
                break;
            case SPACE_IMAGINATION_NOTICE_AMOUNT:
                // 空间畅想通知账号
                smsSpacePojo = SMSSpaceService.sendNoticeSMS(mobile, content, corpid);
                break;
            default:
                LOG.error("短信发送sendApi:case 0已经终止服务 : ", sendApi);
                smsSpacePojo = null;
        }
        return smsSpacePojo;
    }

    /**
     * 获取短信使用条数
     *
     * @param ret 短信服务商返回结果
     * @param entity 短信实体
     * @return
     */
    private int getConsumerCount(SmsSpacePojo ret, SmsStatusEntity entity) {
        if (ret == null || entity == null) {
            return 0;
        }
        int counts = 0;
        if (Objects.equals(ret.getSmsStatus(), "success")) {
            counts = 1;
            String content = entity.getContent();
            if (content.length() > SmsSetConstant.SMS_MAX_LENGTH) {
                /*
                 * 长短信67字一条,防止整除时多加1
                 */
                counts = content.length() / SmsSetConstant.SMS_REAL_LENTTH;
                counts += (content.length() % SmsSetConstant.SMS_REAL_LENTTH == 0) ? 0 : 1;
            }
        }

        return counts;
    }

    /**
     * 设置短信状态
     *
     * @param entity 短信实体
     * @param msgId 短信服务商返回msgId
     * @param statusMemo 短信服务商返回状态信息
     * @param count 使用条数
     */
    private void setSmsStatusEntity(SmsStatusEntity entity,String msgId, String statusMemo, int count) {
        if (count > BasicConstant.ZERO) {
            // 空间畅想成功返回
            entity.setSendTime((long) DateUtil.getInt());
            entity.setStatus(SmsStatusEnum.SEND_ING.getCode());
        } else {
            entity.setSendTime((long) DateUtil.getInt());
            msgId = "err--" + msgId + "--" + DateUtil.getInt();
            entity.setStatus(SmsStatusEnum.FAILURE_SEND.getCode());
            entity.setStatusMemo(statusMemo);
        }
        entity.setMsgId(msgId);
        entity.setUpdateTime((long) DateUtil.getInt());
    }

    /**
     * 设置短信配置信息：用量及扣费
     *
     * @param configEntity 短信配置实体
     * @param count 使用条数
     */
    private void setSmsConfigEntity(SmsConfigEntity configEntity, int count) {
        Integer smsCount = configEntity.getSmsCount();
        Integer sentCount = configEntity.getSentCount();
        if (null == sentCount) {
            sentCount = 0;
        }
        smsCount -= count;
        sentCount += count;
        configEntity.setSmsCount(smsCount);
        Double smsBalance = configEntity.getSmsBalance() == null ? 0D : configEntity.getSmsBalance() - count * 0.05;
        configEntity.setSmsBalance(smsBalance);
        configEntity.setSentCount(sentCount);
        configEntity.setUpdateTime((long) DateUtil.getInt());
    }



    /**
     * @param ret    回调返回数据
     * @param entity 回调的短信实体
     *               创建时间： 很早以前
     *               修改时间： 2019-1-2 下午4:19:18 youli.chen
     * @Description: 短信发送回调处理
     * @author
     * @version v3.15.1
     */
    private void dealSpaceRet(SmsSpacePojo ret, SmsStatusEntity entity) throws XbbException {
        if (ret == null || entity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信回调数据不能为空！");
        }
        try {
            if (Objects.equals(ret.getSmsStatus(), "success")) {
                // 空间畅想成功返回
                entity.setSendTime((long) DateUtil.getInt());
                entity.setStatus(SmsStatusEnum.SEND_ING.getCode());
                smsConfigModel.deductFee(entity.getCorpid(), entity.getContent());
            } else {
                entity.setSendTime((long) DateUtil.getInt());
                ret.setSmsCode("err--" + ret.getSmsCode() + "--" + DateUtil.getInt());
                entity.setStatus(SmsStatusEnum.FAILURE_SEND.getCode());
                entity.setStatusMemo(ret.getSmsMsg());
            }
            entity.setMsgId(ret.getSmsCode());
            entity.setUpdateTime((long) DateUtil.getInt());
            smsStatusModel.update(entity);
        } catch (Exception e) {
            LOG.error("空间畅想dealSpaceRet短信回调异常", e);
        }
    }

    /**
     * @param ret    回调返回数据
     * @param entity 回调的短信实体
     *               创建时间： 很早以前
     *               修改时间： 2018-1-2 下午4:19:18 chy
     * @Description: 短信发送回调处理
     * @author
     * @version v3.15.1
     * @since 很早以前
     */
    private void dealJsonRet(JSONObject ret, SmsStatusEntity entity) throws XbbException {
        if (ret == null || entity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信回调数据不能为空！");
        }
        Integer code = ret.getInteger("code");
        if (code == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信回调返回数据code值不能为空！");
        }
        String msgId = ret.getString("msgId");
        // TODO Auto-generated method stub
        try {
            if (code == 0) {
                //创蓝成功返回
                entity.setSendTime((long) DateUtil.getInt());
                entity.setStatus(SmsStatusEnum.SEND_ING.getCode());
                smsConfigModel.deductFee(entity.getCorpid(), entity.getContent());
            } else {
                entity.setSendTime((long) DateUtil.getInt());
                msgId = "err--" + code + "--" + DateUtil.getInt();
                entity.setStatus(SmsStatusEnum.FAILURE_SEND.getCode());
                entity.setStatusMemo(ret.getString("errorMsg"));
            }
            entity.setMsgId(msgId);
            entity.setUpdateTime((long) DateUtil.getInt());
            smsStatusModel.update(entity);
        } catch (Exception e) {
            LOG.error("dealJsonRet短信回调异常", e);
        }
    }

    /**
     * 校验短信发送时间
     *
     * @param sendType 短信发送类型
     * @param dates    短信发送时间
     * @return
     * @throws XbbException
     */
    private long checkSendTime(Integer sendType, String dates) throws XbbException {
        long sendTime = DateUtil.getInt();
        if (Objects.equals(sendType, SmsSendTypeEnum.DELAY.getCode())) {
            // 发送时间，定时发送必填，时间格式为：yyyy-MM-dd HH:mm
            if (dates == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100019, "短信发送时间不能为空");
            }
            try {
                sendTime = DateUtil.getInt(dates, SDFYMDHM);
            } catch (Exception e) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, "短信发送时间格式错误");
            }
            if (sendTime <= (long) DateUtil.getInt()) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, "短信定时发送时间不能小于当前时间");
            }
        }
        return sendTime;
    }

    /**
     * 短信消费发送
     *
     * @param list     短信记录
     * @param sendType 发送类型
     * @param sendTime 发送时间
     * @return
     * @throws
     * @author hongxiao
     * @date: 2019-04-12 15:47
     * @version v1.0
     * @since v1.0
     */
    private void smsSend(List<SmsStatusEntity> list, Integer sendType, Long sendTime) throws XbbException {
        for (SmsStatusEntity entity : list) {
            if(entity.getReceiver() == null){
                entity.setReceiver("");
            }
            if (Objects.equals(sendType, SmsSendTypeEnum.AT_ONCE.getCode())) {
                smsStatusModel.insert(entity);
                // 创蓝消费短信
                send(entity);
            } else if (Objects.equals(sendType, SmsSendTypeEnum.DELAY.getCode())) {
                entity.setSendTime(sendTime);
                smsStatusModel.insert(entity);
            }
        }
    }

    /**
     * 添加动态
     * @param smsStatusEntities
     * @param corpid
     * @param businessType
     */
    private void addDynamic(List<SmsStatusEntity> smsStatusEntities, String corpid, Integer businessType) {
        try {
            if (CollectionUtils.isNotEmpty(smsStatusEntities)) {
                SmsDynamicStrategy smsDynamicStrategy = dynamicStrategyFactory.getSmsDynamicStrategyByBusinessType(Objects.nonNull(businessType) ? businessType : XbbRefTypeEnum.UNKNOWN.getCode());
                smsDynamicStrategy.send(new DynamicSmsDTO().setSmsStatusEntities(smsStatusEntities));
            }
        } catch (Exception e) {
            LOG.error("com.xbongbong.paas.service.impl.SmsSendServiceImpl.addDynamic", e);
        }
    }

    /**
     * @param corpid
     * @param dataId
     * @Author mingliang
     * @Description 根据公司id数据id查询客户负责人
     * @Date 2022/4/6 10:54
     **/
    private StringBuffer getCustomerOwnerNameByDataId(String corpid, Long dataId) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(StringConstant.DATA_ID, dataId);
        param.put("isMain", 1);
        List<CustomerUserEntity> customerUserEntityList = customerUserModel.findEntitys(param);
        StringBuffer nameBuffer = new StringBuffer();
        if (CollectionsUtil.isEmpty(customerUserEntityList)) {
            return nameBuffer;
        }
        customerUserEntityList.forEach(e -> {
            nameBuffer.append(e.getUserName()).append(StringConstant.COMMA);
        });
        // 删除最后一个为,的字符
        nameBuffer.deleteCharAt(nameBuffer.length() - 1);
        return nameBuffer;
    }

    /**
     * @param corpid
     * @param dataId
     * @Author mingliang
     * @Description 根据公司id数据id查询线索负责人
     * @Date 2022/4/6 10:54
     **/
    private StringBuffer getClueOwnerNameByDataId(String corpid, Long dataId) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(StringConstant.DATA_ID, dataId);
        param.put("isMain", 1);
        List<ClueUserEntity> clueUserList = clueUserModel.findEntitys(param);
        StringBuffer nameBuffer = new StringBuffer();
        if (CollectionsUtil.isEmpty(clueUserList)) {
            return nameBuffer;
        }
        clueUserList.forEach(e -> {
            nameBuffer.append(e.getUserName()).append(StringConstant.COMMA);
        });
        // 删除最后一个为,的字符
        nameBuffer.deleteCharAt(nameBuffer.length() - 1);
        return nameBuffer;
    }

    /**
     * @param corpid
     * @param businessType
     * @param receiver
     * @param formIdList
     * @Author mingliang
     * @Description 根据表单与名称查询负责人
     * @Date 2022/4/6 11:00
     **/
    private StringBuffer getOverName(String corpid, Integer businessType, String receiver, List<Long> formIdList) throws XbbException {
        StringBuffer ownerName = new StringBuffer();
        if (CollectionsUtil.isEmpty(formIdList)) {
            return ownerName;
        }
        PaasFormDataEsMappingDTO paasFormDataEsMappingDTO = new PaasFormDataEsMappingDTO();
        paasFormDataEsMappingDTO.setBusinessType(businessType);
        paasFormDataEsMappingDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
        IndexTypeEnum indexTypeEnum = EsHelper.getIndexTypeEnum(paasFormDataEsMappingDTO);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid", corpid));
        boolQueryBuilder.filter(termsQuery("formId", formIdList));
        boolQueryBuilder.filter(termQuery("del", 0));
        boolQueryBuilder.filter(termQuery("data.text_1.keyword", receiver));
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
        searchRequest.source(sourceBuilder);
        String[] array = {"id"};
        sourceBuilder.fetchSource(array, Strings.EMPTY_ARRAY);
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 0, 10);
        XbbAggregatedPage<PaasFormDataEntityExt> xbbAggregatedPage = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = xbbAggregatedPage.getContent();
        if (CollectionsUtil.isEmpty(paasFormDataEntityExtList)) {
            return ownerName;
        }
        for (int i = 0; i < paasFormDataEntityExtList.size(); i++) {
            PaasFormDataEntityExt paasFormDataEntityExt = paasFormDataEntityExtList.get(i);
            Long dataId = paasFormDataEntityExt.getId();
            StringBuffer ownerNameByDataId = new StringBuffer();
            if (Objects.equals(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), businessType)) {
                ownerNameByDataId = getCustomerOwnerNameByDataId(corpid, dataId);
            } else if (Objects.equals(XbbRefTypeEnum.CLUE.getCode(), businessType)) {
                ownerNameByDataId = getClueOwnerNameByDataId(corpid, dataId);
            }
            ownerName.append(ownerNameByDataId);
        }
        return ownerName;
    }

    /**
     * @param smsRabbitMqDTO
     * @param attr
     * @Author mingliang
     * @Description 根据公司id，businessType，attrList获得有权限的formid列表
     * @Date 2022/4/2 14:24
     **/
    private List<Long> getFormIdList(SmsRabbitMqDTO smsRabbitMqDTO, String attr) throws XbbException {
        List<Long> formIdList = new ArrayList<>();
        if (StringUtil.isEmpty(smsRabbitMqDTO.getCorpid()) || Objects.isNull(smsRabbitMqDTO.getBusinessType()) || StringUtil.isEmpty(attr)) {
            return formIdList;
        }
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid", smsRabbitMqDTO.getCorpid());
        List<Integer>  businessTypeList = new ArrayList<>();
        businessTypeList.add(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
        businessTypeList.add(XbbRefTypeEnum.CLUE.getCode());
        map.put("businessTypeList", businessTypeList);
        map.put("enable", 1);
        map.put("del", 0);
        map.put("distributorMark", 0);
        List<PaasFormEntity> entity = paasFormModel.findEntity(map);
        if (CollectionsUtil.isEmpty(entity)) {
            return formIdList;
        }
        List<Long> tempIdList = new ArrayList<>();
        entity.forEach(e -> {
            tempIdList.add(e.getId());
        });
        return tempIdList;
//        权限不添加了，与之前保持一致
//        List<PaasFormExplainEntity> explainEntityList = paasFormExplainModel.getByFormIdIn(tempIdList, smsRabbitMqDTO.getCorpid());
//        if (CollectionsUtil.isNotEmpty(explainEntityList)) {
//            for (PaasFormExplainEntity paasFormExplainEntity : explainEntityList) {
//                List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
//                HashMap<String, FieldAttrEntity> explainMap = new HashMap<>(fieldAttrEntityList.size());
//                fieldAttrEntityList.forEach(item -> explainMap.put(item.getAttr(), item));
//                if (CollectionsUtil.isEmpty(fieldAttrEntityList)) {
//                    formIdList.add(paasFormExplainEntity.getFormId());
//                } else {
//                    HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
//                    handlerExplainDTO.setExplainList(fieldAttrEntityList);
//                    handlerExplainDTO.setOwnerId(new ArrayList<>());
//                    handlerExplainDTO.setCoUserId(new ArrayList<>());
//                    BeanUtil.copyProperties(smsRabbitMqDTO, handlerExplainDTO);
//                    Boolean fieldNeedHide = ExplainUtil.invisibleOfScope(explainMap.get(attr), handlerExplainDTO);
//                    if (!fieldNeedHide) {
//                        formIdList.add(paasFormExplainEntity.getFormId());
//                    }
//                }
//            }
//        }
//        return formIdList;
    }
}
